﻿namespace Collaboris.Utils
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Xml.Serialization;
    using System.Xml;

    /// <summary>
    /// This class extends the <see cref="T:StringDictionary"/> class to make it 
    /// serializable to XML.
    /// </summary>
    /// <remarks>
    /// The data will be represented in this way:
    ///     <SerializableStringDictionary>
    ///         <DictionaryEntry Key='mykey' Value='myvalue' />
    ///         <DictionaryEntry Key='mykey2' Value='myvalue2' />
    ///     </SerializableStringDictionary>
    /// </remarks>
    [CLSCompliant(true)]
    [Serializable]
    public class SerializableStringDictionary : StringDictionary, IXmlSerializable
    {
        #region IXmlSerializable Members

        /// <summary>
        /// This property is reserved, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"></see> to the class instead.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Xml.Schema.XmlSchema"></see> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"></see> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"></see> method.
        /// </returns>
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        /// <summary>
        /// Generates a collection from its XML representation.
        /// </summary>
        /// <param name="reader">The <see cref="T:System.Xml.XmlReader"></see> stream from which the object is deserialized.</param>
        public void ReadXml(System.Xml.XmlReader reader)
        {
            // Remove existing data from the collection.
            this.Clear();

            string readerXml = reader.ReadOuterXml();
            if(!string.IsNullOrEmpty(readerXml))
            {
                XmlDocument xdReader = new XmlDocument();
                xdReader.LoadXml(readerXml);
                XmlNode xnSerSD = xdReader.SelectSingleNode("Arguments/SerializableStringDictionary");
                if (xnSerSD != null)
                {
                    XmlNodeList xnLstDictionaryEntry = xnSerSD.SelectNodes("DictionaryEntry");
                    if (xnLstDictionaryEntry.Count > 0)
                    {
                        foreach (XmlNode xnDictionaryEntry in xnLstDictionaryEntry)
                        {
                            string key = xnDictionaryEntry.Attributes["Key"].Value;
                            string value = xnDictionaryEntry.Attributes["Value"].Value;
                            this.Add(key, value);
                        }
                    }
                }
            }

            /**
            if (reader.ReadToDescendant("SerializableStringDictionary"))
            {
                if (reader.ReadToDescendant("DictionaryEntry"))
                {
                    do
                    {
                        reader.MoveToAttribute("Key");
                        string key = reader.ReadContentAsString();
                        reader.MoveToAttribute("Value");
                        string value = reader.ReadContentAsString();

                        this.Add(key, value);
                    } while (reader.ReadToNextSibling("DictionaryEntry"));
                }
            }**/
        }

        /// <summary>
        /// Converts an object into its XML representation.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream to which the object is serialized.</param>
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteStartElement("SerializableStringDictionary");

            foreach (DictionaryEntry entry in this)
            {
                writer.WriteStartElement("DictionaryEntry");
                writer.WriteAttributeString("Key", (string)entry.Key);
                writer.WriteAttributeString("Value", (string)entry.Value);
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
        }

        public SerializableStringDictionary()
        {
        }


        public SerializableStringDictionary(HybridDictionary dictionary)
        {
            if (dictionary != null)
            {
                foreach (string dictionaryName in dictionary.Keys)
                {
                    this.Add(dictionaryName, dictionary[dictionaryName].ToString());
                }
            }
        }

        /// <summary>
        /// Returns the String Dictionary as a 
        /// NameValueCollection.
        /// </summary>
        /// <returns></returns>
        public NameValueCollection ToNameValueCollection()
        {
            NameValueCollection nvc = new NameValueCollection();
            foreach (string key in this.Keys)
            {
                nvc.Add(key, this[key]);
            }

            return nvc;
        }

        #endregion

        /// <summary>
        /// Clones the props.
        /// </summary>
        /// <param name="dictionary">The dictionary.</param>
        /// <returns></returns>
        public static SerializableStringDictionary CloneProps(StringDictionary dictionary)
        {
            SerializableStringDictionary cloneDic = new SerializableStringDictionary();
            foreach (string key in dictionary.Keys)
            {
                cloneDic.Add(key, dictionary[key]);
            }
            return cloneDic;
        }

        /// <summary>
        /// Clones the props.
        /// </summary>
        /// <param name="dictionary">The dictionary.</param>
        /// <returns></returns>
        public static SerializableStringDictionary CloneProps(IDictionary<string, string> dictionary)
        {
            SerializableStringDictionary cloneDic = new SerializableStringDictionary();
            foreach (string key in dictionary.Keys)
            {
                cloneDic.Add(key, dictionary[key]);
            }
            return cloneDic;
        }
    }
}